#include "DBInterface.h"


std::string DBInterface::DB_ADDR;
std::string DBInterface::DB_USER;
std::string DBInterface::DB_PWD;
std::string DBInterface::DB_NAME;
int DBInterface::DB_PORT;

int DBInterface::MAX_CONNECTION;
int DBInterface::MIN_CONNECTION;



std::vector<MYSQL*> DBInterface::vec_db_connection;
ACE_Thread_Mutex DBInterface::db_lock;
int DBInterface::db_connection_count = 0;

void DBInterface::Init(const std::string& addr , const std::string& user , const std::string& pwd , const std::string& name , const int port , const int max , const int min)
{
	DB_ADDR = addr;
	DB_USER = user;
	DB_PWD = pwd;
	DB_NAME = name;
	DB_PORT = port;

	MAX_CONNECTION = max;
	MIN_CONNECTION = min;
}

MYSQL* DBInterface::Connect()
{
	MYSQL* db_conn = mysql_init(NULL);

	my_bool recon=true;
	mysql_options(db_conn, MYSQL_OPT_RECONNECT, &recon);

	if( ! mysql_real_connect(db_conn ,	DB_ADDR.c_str() ,DB_USER.c_str() ,DB_PWD.c_str() ,DB_NAME.c_str() ,DB_PORT, NULL, 0))
	{
		printf("DB Conection error : %s\n", mysql_error(db_conn));
		db_conn = NULL;
	}
	return db_conn;
}


void DBInterface::Match2StringValue(MYSQL_BIND * bv , char * buf , int size , bool read )
{
	if(read)
		memset(buf , 0x00 , size);
	bv->buffer_type	= MYSQL_TYPE_VAR_STRING;
	bv->buffer		= buf;
	bv->buffer_length = size;
}

void DBInterface::Match2IntValue(MYSQL_BIND * bv , int * pV)
{
	bv->buffer_type	= MYSQL_TYPE_LONG;
	bv->buffer		= (void*)pV;
	bv->buffer_length = sizeof(int);
}

void DBInterface::Match2DoubleValue(MYSQL_BIND * bv , double * pV)
{
	bv->buffer_type	= MYSQL_TYPE_DOUBLE;
	bv->buffer		= (void*)pV;
	bv->buffer_length = sizeof(double);
}

void DBInterface::Match2CharValue(MYSQL_BIND * bv , char * pV)
{
	bv->buffer_type	= MYSQL_TYPE_STRING;
	bv->buffer		= (void*)pV;
	bv->buffer_length = sizeof(char);
}

_DB_RESULT DBInterface::SelectOne(const std::string& sql , MYSQL_BIND * param , MYSQL_BIND * result)
{
	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;

	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}
 
	if (mysql_stmt_bind_result(stmt, result) != 0) 
	{
		printf("Could not bind results : %s\n" ,sql.c_str() );
		ReleaseConnection(db_conn);
		return _DB_BIND_RESULT_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	if (mysql_stmt_store_result(stmt) != 0) 
	{
		printf("Could not buffer result set : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STORE_ERROR;
	}

	bool ret = false;
	
	 if(mysql_stmt_fetch (stmt) == 0)
	 {
		ret = true;
	 }
	 else
	 {
		printf("no record\n");
	 }

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);

	ReleaseConnection(db_conn);

	return _DB_SUCCESS;
}

_DB_RESULT DBInterface::Execute(const std::string& sql , MYSQL_BIND * param)
{
	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;


	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);


	ReleaseConnection(db_conn);

	return _DB_SUCCESS;
}


MYSQL* DBInterface::GetConnection()
{
	MYSQL * conn = NULL;

	for(int i = 0 ; i < DB_CONNECTION_TRY_COUNT+1 && conn == NULL; i++)
	{
		if(i > 0)
			sleep(1);

		db_lock.acquire();

		if(vec_db_connection.size() > 0)
		{
			conn = vec_db_connection[vec_db_connection.size() -1];
			vec_db_connection.pop_back();
		}
		else if(db_connection_count < MAX_CONNECTION)
		{
			conn = Connect();
			if(conn != NULL)
			{
				db_connection_count++;
				printf("add db connection : %d\n" , db_connection_count);
			}
		}

		db_lock.release();
	}

	return conn;

}

void DBInterface::ReleaseConnection(MYSQL* conn)
{	
	db_lock.acquire();

	if(db_connection_count > MIN_CONNECTION)
	{
		db_connection_count --;
		mysql_close(conn);
		printf("del db connection : %d\n" ,  db_connection_count);
	}
	else
	{
		vec_db_connection.push_back(conn);
	}

	db_lock.release();
}

void DBInterface::DeleteAllConnections()
{
	while(true)
	{
		db_lock.acquire();

		if(db_connection_count == 0 || db_connection_count == vec_db_connection.size())
		{
			while(vec_db_connection.size() > 0)
			{
				MYSQL* conn = vec_db_connection[vec_db_connection.size() -1];
				vec_db_connection.pop_back();

				mysql_close(conn);
			}

			printf("delete all DB connections[%d]\n" , db_connection_count);

			db_connection_count = 0;

			db_lock.release();

			break;

		}

		db_lock.release();

		sleep(1);
	}

}

_DB_RESULT DBInterface::AddAgent(const std::string& renderer_id , const std::string& agent_ip)
{
#ifdef _TEST_
	return true;
#endif


	MYSQL_BIND param[2];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);
	DBInterface::Match2StringValue(&param[1] , (char*)agent_ip.c_str() , agent_ip.length(), false);

	std::string sql = "DELETE FROM TBL_CONNECTED_AGENT WHERE RENDERER_ID = ? AND  AGENT_IP = ?";
	_DB_RESULT result = DBInterface::Execute(sql , param);
	if(_DB_SUCCESS != result)
		return result;

	sql = "INSERT INTO TBL_CONNECTED_AGENT(RENDERER_ID , AGENT_IP) VALUES(?,?)";
	return DBInterface::Execute(sql , param);
};

_DB_RESULT DBInterface::DelAgent(const std::string& renderer_id , const std::string& agent_ip)
{
#ifdef _TEST_
	return true;
#endif
	std::string sql = "DELETE FROM TBL_CONNECTED_AGENT WHERE RENDERER_ID=? AND AGENT_IP=?"; 

	MYSQL_BIND param[2];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);
	DBInterface::Match2StringValue(&param[1] , (char*)agent_ip.c_str() , agent_ip.length(), false);

	return DBInterface::Execute(sql , param);
};

_DB_RESULT DBInterface::ClearProcessingJobs(const std::string& renderer_id , const std::string& agent_ip)
{

	std::string sql = "DELETE FROM TBL_PROCESSING_JOB WHERE RENDERER_ID=? AND AGENT_IP=?";

	MYSQL_BIND param[2];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);
	DBInterface::Match2StringValue(&param[1] , (char*)agent_ip.c_str() , agent_ip.length(), false);

	return DBInterface::Execute(sql , param);
};



_DB_RESULT DBInterface::AddJob(const std::string& renderer_id , const std::string& agent_ip , const std::string& job_id)
{

	std::string sql = "INSERT INTO TBL_PROCESSING_JOB(RENDERER_ID , AGENT_IP , JOB_ID) VALUES( ? , ? , ? )";

	MYSQL_BIND param[3];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);
	DBInterface::Match2StringValue(&param[1] , (char*)agent_ip.c_str() , agent_ip.length(), false);
	DBInterface::Match2StringValue(&param[2] , (char*)job_id.c_str() , job_id.length(), false);

	return DBInterface::Execute(sql , param);
};

_DB_RESULT DBInterface::DelJobList(const std::vector<std::string>& vecJobId)
{
	if(vecJobId.size() == 0)
		return _DB_SUCCESS;
	if(vecJobId.size() == 1)
		return DelJob(vecJobId[0]);

	std::string sql = "DELETE FROM TBL_PROCESSING_JOB WHERE JOB_ID IN ("; 
	for(int i = 0 ; i < vecJobId.size() ; i ++)
	{
		if(i > 0)
			sql += ",";
		sql += std::string("'") + vecJobId[i] + "'";
	}
	sql += ")";

	return DBInterface::Execute(sql , NULL);

}

_DB_RESULT DBInterface::DelJob(const std::string& job_id)
{
	std::string sql = "DELETE FROM TBL_PROCESSING_JOB WHERE JOB_ID=?"; 

	MYSQL_BIND param[1];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)job_id.c_str() , job_id.length(), false);

	return DBInterface::Execute(sql , param);

};

_DB_RESULT DBInterface::ResetMonitorData(const std::string& renderer_id)
{

	MYSQL_BIND param[1];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);

	std::string sql = "DELETE FROM TBL_CONNECTED_AGENT WHERE RENDERER_ID=?";
	_DB_RESULT result = DBInterface::Execute(sql , param);
	if(_DB_SUCCESS != result)
		return result;

	sql = "DELETE FROM TBL_PROCESSING_JOB WHERE RENDERER_ID=?";
	return DBInterface::Execute(sql , param);


}

_DB_RESULT DBInterface::GetAgentStates(const std::string& renderer_id , std::map<std::string , _SOCKET_STATE>& agent_map)
{
	agent_map.clear();


	MYSQL_BIND param[1] , result[3];

	std::string sql = "SELECT R.AGENT_IP , R.ACTIVE , C.STATE FROM TBL_CONNECTED_AGENT C , TBL_REG_AGENT R WHERE R.RENDERER_ID = C.RENDERER_ID AND R.AGENT_IP = C.AGENT_IP AND C.RENDERER_ID=?";

	memset (param, 0x00, sizeof (param)); 
	memset (result, 0x00, sizeof (result)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false );

	char agent_ip[20] , active , state;
	DBInterface::Match2StringValue(&result[0] , agent_ip , sizeof(agent_ip) , true );
	DBInterface::Match2CharValue(&result[1] , &active);
	DBInterface::Match2CharValue(&result[2] , &state);

	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;

	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}
 
	if (mysql_stmt_bind_result(stmt, result) != 0) 
	{
		printf("Could not bind results : %s\n" ,sql.c_str() );
		ReleaseConnection(db_conn);
		return _DB_BIND_RESULT_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	if (mysql_stmt_store_result(stmt) != 0) 
	{
		printf("Could not buffer result set : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STORE_ERROR;
	}
	
	 while(mysql_stmt_fetch (stmt) == 0)
	 {
		 if( (active == 'F' || active == 'f') && (state == 'R' || state=='r'))
		 {
			 printf("agent[%s] is not active\n" , agent_ip);
			 state = 'S';
			 SetStoppingAgent(renderer_id , agent_ip);
		 }

		 switch(state)
		 {
		 case 'S':
		 case's':
			agent_map[agent_ip] = _STOPPING;
			 break;
		 case 'D':
		 case 'd':
			agent_map[agent_ip] = _STOPPED;
			 break;
		 default:
			agent_map[agent_ip] = _RUNNING;
		 }

	 }

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);

	ReleaseConnection(db_conn);

	return _DB_SUCCESS;
}


_DB_RESULT DBInterface::SetStoppedAgent(const std::string& renderer_id , const std::string& agent_ip)
{
	MYSQL_BIND param[2];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);
	DBInterface::Match2StringValue(&param[1] , (char*)agent_ip.c_str() , agent_ip.length() , false);

	std::string sql = "UPDATE TBL_CONNECTED_AGENT SET STATE='D' WHERE RENDERER_ID=? AND AGENT_IP=? AND STATE IN ('S' , 's')";

	return DBInterface::Execute(sql , param);
}

_DB_RESULT DBInterface::SetStoppingAgent(const std::string& renderer_id , const std::string& agent_ip)
{
	MYSQL_BIND param[2];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);
	DBInterface::Match2StringValue(&param[1] , (char*)agent_ip.c_str() , agent_ip.length() , false);

	std::string sql = "UPDATE TBL_CONNECTED_AGENT SET STATE='S' WHERE RENDERER_ID=? AND AGENT_IP=? AND STATE IN ('R' , 'r')";

	return DBInterface::Execute(sql , param);
}

_DB_RESULT DBInterface::SetStoppingAgents(const std::string& renderer_id , const std::vector<std::string>& vec_ip)
{
	if(vec_ip.size() == 0)
		return _DB_SUCCESS;

	MYSQL_BIND param[1];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);

	std::string tmp = "";
	for(int i = 0 ; i < vec_ip.size() ; i ++)
	{
		if(0 == i)
			tmp += std::string("'") + vec_ip[i] + std::string("'");
		else
			tmp += std::string(",'") + vec_ip[i] + std::string("'");
	}

	std::string sql = "UPDATE TBL_CONNECTED_AGENT SET STATE='S' WHERE RENDERER_ID=? AND AGENT_IP IN (" + tmp + ") AND STATE IN ('R' , 'r')";

	return DBInterface::Execute(sql , param);
}



_DB_RESULT DBInterface::GetRegInstanceList(const std::string& renderer_id , std::vector<std::string>& vecInstance , const bool always )
{
	vecInstance.clear();

	MYSQL_BIND param[1] , result[1];

	std::string sql = "SELECT INSTANCE_ID FROM TBL_REG_AGENT WHERE RENDERER_ID=? AND ACTIVE IN ('T','t') ";
	if(always)
	{
		sql += "AND ALWAYS IN ('T','t') ";
	}


	memset (param, 0x00, sizeof (param)); 
	memset (result, 0x00, sizeof (result)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false );

	char instance_id[100];
	DBInterface::Match2StringValue(&result[0] , instance_id , sizeof(instance_id) , true );

	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;

	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}
 
	if (mysql_stmt_bind_result(stmt, result) != 0) 
	{
		printf("Could not bind results : %s\n" ,sql.c_str() );
		ReleaseConnection(db_conn);
		return _DB_BIND_RESULT_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	if (mysql_stmt_store_result(stmt) != 0) 
	{
		printf("Could not buffer result set : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STORE_ERROR;
	}
	
	 while(mysql_stmt_fetch (stmt) == 0)
	 {
		 vecInstance.push_back(instance_id);
	 }

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);

	ReleaseConnection(db_conn);

	return _DB_SUCCESS;
}


_DB_RESULT DBInterface::GetRegInstanceCount( const std::string& renderer_id , int& count , const bool always )
{

	MYSQL_BIND param[1] , result[1];

	std::string sql = "SELECT COUNT(*) FROM TBL_REG_AGENT WHERE RENDERER_ID=? AND ACTIVE IN ('T','t') ";
	if(always)
	{
		sql += "AND ALWAYS IN ('T','t') ";
	}


	memset (param, 0x00, sizeof (param)); 
	memset (result, 0x00, sizeof (result)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false );

	DBInterface::Match2IntValue(&result[0] , &count);

	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;

	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}
 
	if (mysql_stmt_bind_result(stmt, result) != 0) 
	{
		printf("Could not bind results : %s\n" ,sql.c_str() );
		ReleaseConnection(db_conn);
		return _DB_BIND_RESULT_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	if (mysql_stmt_store_result(stmt) != 0) 
	{
		printf("Could not buffer result set : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STORE_ERROR;
	}
	
	 mysql_stmt_fetch (stmt);

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);

	ReleaseConnection(db_conn);

	return _DB_SUCCESS;
}


_DB_RESULT DBInterface::GetStoppedAgentInstanceList(const std::string& renderer_id , std::vector<std::string>& vecInstance)
{
	vecInstance.clear();

	MYSQL_BIND param[1] , result[1];

	std::string sql = "SELECT R.INSTANCE_ID FROM TBL_REG_AGENT R , TBL_CONNECTED_AGENT C WHERE R.AGENT_IP = C.AGENT_IP AND C.STATE IN ('D','d') AND R.RENDERER_ID = C.RENDERER_ID AND C.RENDERER_ID=? ";

	memset (param, 0x00, sizeof (param)); 
	memset (result, 0x00, sizeof (result)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false );

	char instance_id[100];
	DBInterface::Match2StringValue(&result[0] , instance_id , sizeof(instance_id) , true );

	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;

	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}
 
	if (mysql_stmt_bind_result(stmt, result) != 0) 
	{
		printf("Could not bind results : %s\n" ,sql.c_str() );
		ReleaseConnection(db_conn);
		return _DB_BIND_RESULT_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	if (mysql_stmt_store_result(stmt) != 0) 
	{
		printf("Could not buffer result set : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STORE_ERROR;
	}
	
	 while(mysql_stmt_fetch (stmt) == 0)
	 {
		 vecInstance.push_back(instance_id);
	 }

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);

	ReleaseConnection(db_conn);

	return _DB_SUCCESS;
}


_DB_RESULT DBInterface::GetRunningAgentInstanceList(const std::string& renderer_id , std::vector<std::string>& vecInstance)
{
	vecInstance.clear();

	MYSQL_BIND param[1] , result[1];

	std::string sql = "SELECT R.INSTANCE_ID FROM TBL_REG_AGENT R , TBL_CONNECTED_AGENT C WHERE R.ALWAYS NOT IN ('T','t') AND R.AGENT_IP = C.AGENT_IP AND C.STATE IN ('R','r') AND R.RENDERER_ID = C.RENDERER_ID AND C.RENDERER_ID=? ";

	memset (param, 0x00, sizeof (param)); 
	memset (result, 0x00, sizeof (result)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false );

	char instance_id[100];
	DBInterface::Match2StringValue(&result[0] , instance_id , sizeof(instance_id) , true );

	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;

	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}
 
	if (mysql_stmt_bind_result(stmt, result) != 0) 
	{
		printf("Could not bind results : %s\n" ,sql.c_str() );
		ReleaseConnection(db_conn);
		return _DB_BIND_RESULT_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	if (mysql_stmt_store_result(stmt) != 0) 
	{
		printf("Could not buffer result set : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STORE_ERROR;
	}
	
	 while(mysql_stmt_fetch (stmt) == 0)
	 {
		 vecInstance.push_back(instance_id);
	 }

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);

	ReleaseConnection(db_conn);

	return _DB_SUCCESS;
}


_DB_RESULT DBInterface::GetAgentMode( const std::string& renderer_id , const std::string& agent_ip , char& mode)
{
	MYSQL_BIND param[2] , result[1];

	std::string sql = "SELECT ACTIVE FROM TBL_REG_AGENT WHERE RENDERER_ID=? AND AGENT_IP=? ";

	memset (param, 0x00, sizeof (param)); 
	memset (result, 0x00, sizeof (result)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false );
	DBInterface::Match2StringValue(&param[1] , (char*)agent_ip.c_str() , agent_ip.length() , false );


	DBInterface::Match2CharValue(&result[0] ,&mode);

	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;

	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}
 
	if (mysql_stmt_bind_result(stmt, result) != 0) 
	{
		printf("Could not bind results : %s\n" ,sql.c_str() );
		ReleaseConnection(db_conn);
		return _DB_BIND_RESULT_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	if (mysql_stmt_store_result(stmt) != 0) 
	{
		printf("Could not buffer result set : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STORE_ERROR;
	}
	
	 mysql_stmt_fetch (stmt);

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);

	ReleaseConnection(db_conn);

	return _DB_SUCCESS;
}

_DB_RESULT DBInterface::GetControllerTimeElapsed(const std::string& renderer_id , int& primary_elapsed , int& secondary_elapsed)
{
	MYSQL_BIND param[1] , result[2];

	std::string sql = "select TIMESTAMPDIFF(SECOND , PRIMARY_TIME , now()) ,TIMESTAMPDIFF(SECOND , SECONDARY_TIME , now())  from TBL_CONTROLLER_TIME WHERE RENDERER_ID=? ";

	memset (param, 0x00, sizeof (param)); 
	memset (result, 0x00, sizeof (result)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false );

	DBInterface::Match2IntValue(&result[0] ,&primary_elapsed);
	DBInterface::Match2IntValue(&result[1] ,&secondary_elapsed);

	MYSQL* db_conn = GetConnection();
	if(db_conn == NULL)
		return _DB_NO_CONNECTION;

	MYSQL_STMT * stmt = mysql_stmt_init(db_conn);

	if (stmt == NULL) 
	{
		printf("Could not initialize statement handler : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STMT_ERROR;
	}

	if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) 
	{
		printf("Could not prepare statement : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_PREPARE_ERROR;
	}

	if (param!= NULL && mysql_stmt_bind_param(stmt, param) != 0) 
	{
		printf("Could not bind parameters : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_BIND_PARAM_ERROR;
	}
 
	if (mysql_stmt_bind_result(stmt, result) != 0) 
	{
		printf("Could not bind results : %s\n" ,sql.c_str() );
		ReleaseConnection(db_conn);
		return _DB_BIND_RESULT_ERROR;
	}

	if (mysql_stmt_execute(stmt) != 0) 
	{
		printf("Could not execute statement : %s\n", sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_EXE_ERROR;
	}

	if (mysql_stmt_store_result(stmt) != 0) 
	{
		printf("Could not buffer result set : %s\n" , sql.c_str());
		ReleaseConnection(db_conn);
		return _DB_STORE_ERROR;
	}
	
	 mysql_stmt_fetch (stmt);

	 mysql_stmt_free_result(stmt); 
	 mysql_stmt_close(stmt);

	ReleaseConnection(db_conn);


	return _DB_SUCCESS;
}

_DB_RESULT DBInterface::SetControllerTime(const std::string& renderer_id  , const bool is_primary)
{
	MYSQL_BIND param[1];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);

	std::string sql;
	
	if(is_primary)
		sql = "UPDATE TBL_CONTROLLER_TIME SET PRIMARY_TIME=now() WHERE RENDERER_ID=? ";
	else
		sql = "UPDATE TBL_CONTROLLER_TIME SET SECONDARY_TIME=now() WHERE RENDERER_ID=? ";

	return DBInterface::Execute(sql , param);
}

#ifdef _TEST_
bool DBInterface::test_SetAllStoppingAgentsToStop(const std::string& renderer_id)
{
	MYSQL_BIND param[1];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);

	std::string sql = "UPDATE TBL_CONNECTED_AGENT SET STATE='D' WHERE STATE IN('S','s') AND RENDERER_ID=? ";

	return DBInterface::Execute(sql , param);
}

bool DBInterface::test_SetRunningAgent(const std::string& renderer_id , const std::string& instance_id)
{
	MYSQL_BIND param[3];
	memset (param, 0x00, sizeof (param)); 

	DBInterface::Match2StringValue(&param[0] , (char*)renderer_id.c_str() , renderer_id.length() , false);
	DBInterface::Match2StringValue(&param[1] , (char*)instance_id.c_str() , instance_id.length() , false);
	DBInterface::Match2StringValue(&param[2] , (char*)renderer_id.c_str() , renderer_id.length() , false);

	std::string sql = "UPDATE TBL_CONNECTED_AGENT SET STATE='R' WHERE RENDERER_ID=? AND AGENT_IP IN (SELECT AGENT_IP FROM TBL_REG_AGENT WHERE INSTANCE_ID=? AND RENDERER_ID=?) ";
	return DBInterface::Execute(sql , param);
}

#endif
